package service

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"

	pb "lakeFS/api/lakefstest" // 导入protobuf生成的接口定义
)

// LakefstestService 实现lakeFS的gRPC服务接口
type LakefstestService struct {
	pb.UnimplementedLakefstestServer        // 内嵌未实现的基类（protobuf要求）
	apiEndpoint                      string // lakeFS API地址，例如: "http://localhost:8000/api/v1"
	accessKey                        string // 认证access key
	secretKey                        string // 认证secret key
}

// NewLakefstestService 创建服务实例的构造函数
// 参数:
//   - apiEndpoint: lakeFS API地址
//   - accessKey: 认证access key
//   - secretKey: 认证secret key
//
// 返回:
//   - *LakefstestService: 初始化好的服务实例
func NewLakefstestService(apiEndpoint, accessKey, secretKey string) *LakefstestService {
	return &LakefstestService{
		apiEndpoint: apiEndpoint,
		accessKey:   accessKey,
		secretKey:   secretKey,
	}
}

// CreateRepository 创建新的数据仓库
// 参数:
//   - ctx: 上下文，用于超时和取消控制
//   - req: 包含仓库名称和存储空间的请求参数
//
// 返回:
//   - *pb.CreateRepositoryResponse: 创建成功的响应数据
//   - error: 错误信息（如果有）

func (s *LakefstestService) CreateRepository(ctx context.Context, req *pb.CreateRepositoryRequest) (*pb.CreateRepositoryResponse, error) {
	// 构造API请求URL
	url := fmt.Sprintf("%s/api/v1/repositories", s.apiEndpoint)

	// 构造请求体
	payload := strings.NewReader(fmt.Sprintf(`{
		"name": "%s",
		"storage_namespace": "local://%s",
		"default_branch": "main",
		"sample_data": false
		}`, req.Name, req.Name))

	// 发送请求
	resp, err := s.sendRequest(ctx, "POST", url, payload)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 解析响应
	var result struct {
		ID               string `json:"id"`
		CreationDate     int64  `json:"creation_date"`
		DefaultBranch    string `json:"default_branch"`
		StorageID        string `json:"storage_id"`
		StorageNamespace string `json:"storage_namespace"`
		ReadOnly         bool   `json:"read_only"`
	}
	// 打印原始响应
	// bodyBytes, err := io.ReadAll(resp.Body)
	// if err != nil {
	// 	return nil, fmt.Errorf("failed to read response: %v", err)
	// }
	// log.Println("Raw Response:", string(bodyBytes))
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("decode response failed: %v", err)
	}

	// 构造protobuf响应
	return &pb.CreateRepositoryResponse{
		Id:            result.ID,
		CreationDate:  string(result.CreationDate),
		DefaultBranch: result.DefaultBranch,
	}, nil
}

// ListRepositories 获取仓库列表（支持分页）
// 参数:
//   - ctx: 上下文
//   - req: 包含分页参数(limit/after)的请求
//
// 返回:
//   - *pb.ListRepositoriesResponse: 仓库列表和分页标记
//   - error: 错误信息
func (s *LakefstestService) ListRepositories(ctx context.Context, req *pb.ListRepositoriesRequest) (*pb.ListRepositoriesResponse, error) {
	// 构造带分页参数的URL
	// url := fmt.Sprintf("%s/repositories?limit=%d&after=%s", s.apiEndpoint, req.Limit, req.After)
	url := fmt.Sprintf("%s/api/v1/repositories", s.apiEndpoint)
	// 发送GET请求
	resp, err := s.sendRequest(ctx, "GET", url, nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 定义响应结构体
	var result struct {
		Pagination struct {
			HasMore    bool   `json:"has_more"`
			NextOffset string `json:"next_offset"`
			Results    int    `json:"results"`
			MaxPerPage int    `json:"max_per_page"`
		} `json:"pagination"`
		Results []struct {
			ID               string `json:"id"`
			CreationDate     int64  `json:"creation_date"` // 图片中显示为数字(0)
			DefaultBranch    string `json:"default_branch"`
			StorageID        string `json:"storage_id"`
			StorageNamespace string `json:"storage_namespace"`
			ReadOnly         bool   `json:"read_only"`
		} `json:"results"`
	}

	// 解析JSON
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("decode response failed: %v", err)
	}

	// 转换结果到protobuf格式
	repos := make([]*pb.Repository, 0, len(result.Results))
	for _, r := range result.Results {
		repos = append(repos, &pb.Repository{
			Id:               r.ID,
			StorageNamespace: r.StorageNamespace,
			CreationDate:     string(r.CreationDate),
			DefaultBranch:    r.DefaultBranch,
		})
	}

	// 返回带分页标记的结果
	return &pb.ListRepositoriesResponse{
		Repositories: repos,
		Next:         "result.Pagination.Next",
	}, nil
}

// DeleteRepository 删除指定仓库
// 参数:
//   - ctx: 上下文
//   - req: 包含仓库名称的请求
//
// 返回:
//   - *pb.DeleteRepositoryResponse: 删除是否成功的状态
//   - error: 错误信息
func (s *LakefstestService) DeleteRepository(ctx context.Context, req *pb.DeleteRepositoryRequest) (*pb.DeleteRepositoryResponse, error) {
	// 构造带仓库名称的URL
	url := fmt.Sprintf("%s/api/v1/repositories/%s", s.apiEndpoint, req.Repository)

	// 发送DELETE请求
	resp, err := s.sendRequest(ctx, "DELETE", url, nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 根据状态码判断是否成功(204 No Content表示成功)
	return &pb.DeleteRepositoryResponse{Success: resp.StatusCode == http.StatusNoContent}, nil
}

// UploadObject 上传文件到指定仓库的分支
// 参数:
//   - ctx: 上下文
//   - req: 包含仓库名、分支名、路径和文件内容的请求
//
// 返回:
//   - *pb.UploadObjectResponse: 上传结果（路径、大小、校验和）
//   - error: 错误信息
func (s *LakefstestService) UploadObject(ctx context.Context, req *pb.UploadObjectRequest) (*pb.UploadObjectResponse, error) {
	// 构造对象上传URL
	url := fmt.Sprintf("%s/api/v1/repositories/%s/branches/%s/objects", s.apiEndpoint, req.Repository, req.Branch)

	// 发送带文件内容的请求
	resp, err := s.sendRequestWithContent(ctx, "POST", url, req.Path, req.Content)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 解析上传结果
	var result struct {
		Path                  string            `json:"path"`
		PathType              string            `json:"path_type"`
		PhysicalAddress       string            `json:"physical_address"`
		PhysicalAddressExpiry int64             `json:"physical_address_expiry"`
		Checksum              string            `json:"checksum"`
		SizeBytes             int64             `json:"size_bytes"`
		Mtime                 int64             `json:"mtime"`
		Metadata              map[string]string `json:"metadata"`
		ContentType           string            `json:"content_type"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("decode response failed: %v", err)
	}
	log.Println(result)

	// 返回上传结果
	return &pb.UploadObjectResponse{
		Path:     result.Path,
		Size:     result.SizeBytes,
		Checksum: result.Checksum,
	}, nil
}

// sendRequest 通用HTTP请求方法
// 参数:
//   - ctx: 上下文
//   - method: HTTP方法(POST/GET等)
//   - url: 请求URL
//   - body: 请求体内容
//
// 返回:
//   - *http.Response: HTTP响应
//   - error: 错误信息
func (s *LakefstestService) sendRequest(ctx context.Context, method, url string, body io.Reader) (*http.Response, error) {
	// 创建带上下文的请求
	req, err := http.NewRequestWithContext(ctx, method, url, body)
	if err != nil {
		return nil, err
	}

	// 设置认证头和内容类型
	req.SetBasicAuth(s.accessKey, s.secretKey)
	req.Header.Set("Content-Type", "application/json")

	// 发送请求
	return http.DefaultClient.Do(req)
}

// sendRequestWithContent 带二进制内容的上传专用请求方法
// 参数:
//   - ctx: 上下文
//   - method: HTTP方法
//   - url: 基础URL
//   - path: 文件路径（会作为查询参数追加）
//   - content: 文件二进制内容
//
// 返回:
//   - *http.Response: HTTP响应
//   - error: 错误信息
func (s *LakefstestService) sendRequestWithContent(ctx context.Context, method, url, path string, content []byte) (*http.Response, error) {
	// 创建带路径参数的请求
	req, err := http.NewRequestWithContext(ctx, method, fmt.Sprintf("%s?path=%s", url, path), bytes.NewReader(content))
	if err != nil {
		return nil, err
	}

	// 设置认证头（不需要Content-Type，因为可能是任意二进制文件）
	req.Header.Set("Content-Type", "application/octet-stream")
	req.SetBasicAuth(s.accessKey, s.secretKey)
	// req.Header.Set("Content-Type", "multipart/form-data")
	// 发送请求
	return http.DefaultClient.Do(req)
}
